﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Globalization;

namespace Chilis.Marketing.Common
{
    public static class StringHelper
    {
        /// <summary>
        /// Remove the given value from the end of a string
        /// </summary>
        /// <param name="value">Is the string to be searched.</param>		
        /// <param name="remove">Is the string to be removed from the end.</param>
        /// <returns></returns>
        /// <example>
        /// <code>
        ///		// str will have value "rapto"
        ///		string str = StringHelper.RemoveFromEnd("raptor", "r");
        ///
        ///		// str will have value "raptor" as it does not end with "w"
        ///		str = StringHelper.RemoveFromEnd("raptor", "w");
        ///
        ///		// str will have value "" because the entire string is removed
        ///		str = StringHelper.RemoveFromEnd("raptor", "raptor");
        /// </code>
        /// </example>
        public static string RemoveFromEnd(string value, string remove)
        {
            // if either str value is null throw exception 
            if (value == null) throw new ArgumentNullException("value");
            if (remove == null) throw new ArgumentNullException("remove");

            // if found and the end remove it
            string result = value;
            int p = value.LastIndexOf(remove, StringComparison.OrdinalIgnoreCase);

            if (p != -1)
                if (p + remove.Length == value.Length)
                    result = value.Remove(p);
            return result;
        }

        /// <summary>
        /// Applies a format mask to a string to generate a new string.
        /// </summary>
        /// <param name="text">The string to be formatted</param>
        /// <param name="mask">The mask to apply</param>
        /// <param name="placeholder">The placeholder.</param>
        /// <returns>The formatted source string</returns>
        /// <remarks>This method performs string formatting by replacing
        /// occurrences of <paramref name="placeHolder"/> in <paramref name="mask"/>
        /// with consecutive characters from <paramref name="source"/>.
        /// Substitution proceeds from left to right. Any unused characters in
        /// <paramref name="text"/> are ignored. If <paramref name="text"/>
        /// does not have enough characters, remaining mask characters are
        /// replaced with spaces.
        /// </remarks>
        public static string MaskedFormat(string text, string mask, char placeholder)
        {
            // if either str value is null throw exception 
            if (text == null) throw new ArgumentNullException("text");
            if (mask == null) throw new ArgumentNullException("mask");

            int nextSourceChar = 0;
            char[] maskedChars = mask.ToCharArray();
            char[] sourceChars = text.ToCharArray();

            for (int i = 0; i < maskedChars.Length; i++)
            {
                if (maskedChars[i] == placeholder)
                {
                    maskedChars[i] =
                        nextSourceChar >= sourceChars.Length ?
                        ' ' : sourceChars[nextSourceChar++];
                }
            }
            return new string(maskedChars);
        }

        /// <summary>
        /// Maskeds the format left to right.
        /// </summary>
        /// <param name="text">The text.</param>
        /// <param name="mask">The mask.</param>
        /// <param name="placeholder">The placeholder.</param>
        /// <returns></returns>
        public static string MaskedFormatLeftToRight(string text, string mask, char placeholder)
        {
            // if either str value is null throw exception 
            if (text == null) throw new ArgumentNullException("text");
            if (mask == null) throw new ArgumentNullException("mask");

            int nextSourceChar = 0;
            char[] maskedChars = mask.ToCharArray();
            char[] sourceChars = text.ToCharArray();
            String remaining;

            for (int i = 0; i < maskedChars.Length; i++)
            {
                if (maskedChars[i] == placeholder)
                {
                    maskedChars[i] =
                        nextSourceChar >= sourceChars.Length ?
                        ' ' : sourceChars[nextSourceChar++];
                }
            }
            remaining = new String(sourceChars);
            remaining = remaining.Substring(nextSourceChar, remaining.Length - nextSourceChar);
            return new string(maskedChars) + remaining;
        }

        /// <summary>
        /// Replaces the format item in a specified String with the text equivalent of the value 
        /// of a corresponding Object instance in a specified array. The invariant culture is used
        /// for datetime and numeric data formating.
        /// </summary>
        /// <remarks>
        /// Appropriate for formatting strings to be used internally within the code.  
        /// Use <see cref="FormatForUI"/> for strings that will be output to the UI.
        /// </remarks>
        /// <param name="format">A <see cref="String"/> containing zero or more format items. </param>
        /// <param name="args">An <see cref="Object"/> array containing zero or more objects to format.</param>
        /// <returns>
        /// A copy of format in which the format items have been replaced by the String 
        /// equivalent of the corresponding instances of Object in args. 
        /// </returns>
        /// <seealso cref="String.Format(String, Object[])"/>
        public static string FormatForCode(string format, params object[] args)
        {
            return string.Format(CultureInfo.InvariantCulture, format, args);
        }

        /// <summary>
        /// Replaces the format item in a specified String with the text equivalent of the value 
        /// of a corresponding Object instance in a specified array. The current culture is used
        /// for datetime and numeric data formating.
        /// </summary>
        /// <remarks>
        /// Appropriate for formatting strings that will be output to the UI. 
        /// Use <see cref="FormatForCode"/> for strings to be used internally within the code.  
        /// </remarks>
        /// <param name="format">A <see cref="String"/> containing zero or more format items. </param>
        /// <param name="args">An <see cref="Object"/> array containing zero or more objects to format.</param>
        /// <returns>
        /// A copy of format in which the format items have been replaced by the String 
        /// equivalent of the corresponding instances of Object in args. 
        /// </returns>
        /// <seealso cref="String.Format(String, Object[])"/>
        public static string FormatForUI(string format, params Object[] args)
        {
            return string.Format(CultureInfo.CurrentCulture, format, args);
        }

        /// <summary>
        /// Capitalizes the specified text.
        /// </summary>
        /// <param name="text">The text.</param>
        /// <returns>
        /// The same string but with the first letter capitalized.
        /// </returns>
        public static string Capitalize(string text)
        {
            if (text == null) throw new ArgumentNullException("text");
            if (text.Trim().Length > 0)
            {
                StringBuilder stringBuilder = new StringBuilder(text.Trim().ToUpperInvariant());
                stringBuilder[0] = Char.ToUpperInvariant(stringBuilder[0]);
                return stringBuilder.ToString();
            }
            else
            {
                return String.Empty;
            }
        }


        /// <summary>
        /// Converts string to bool.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <returns>System.Boolean</returns>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1720:IdentifiersShouldNotContainTypeNames", MessageId = "bool")]
        public static bool ConvertToBool(int value)
        {
            try
            {
                return Convert.ToBoolean(value);
            }
            catch (InvalidCastException)
            {
                return false;
            }
        }

        /// <summary>
        /// Gets the value or default if the selected value is null or an empty string.
        /// </summary>
        /// <param name="selectedValue">The selected value.</param>
        /// <param name="defaultValue">The default value.</param>
        /// <returns>
        /// System.String<seealso cref="System.String"/>
        /// </returns>
        public static string GetValueOrDefault(string selectedValue, string defaultValue)
        {
            return (String.IsNullOrEmpty(selectedValue)) ? defaultValue : selectedValue;
        }

        /// <summary>
        /// Converts to nullable int.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <returns>System.Nullable&lt;System.Int32&gt;</returns>
        public static int? ConvertToNullableInt(string value)
        {
            int temp;
            return int.TryParse(value, out temp) ? new int?(temp) : new int?();
        }
    }
}
